﻿namespace Cellfish.Toolbox.Streams
{
    using System;
    using System.IO;

    /// <summary>
    /// Implements a stream wrapper that counts the number of bytes written and
    /// read.
    /// </summary>
    public class CountingStream : PassThruStream
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="CountingStream"/> class.
        /// </summary>
        /// <param name="stream">The stream to wrap.</param>
        public CountingStream(Stream stream)
            : base(stream)
        {
            this.BeforeRead = null;
            this.BeforeWrite = null;
            this.AfterRead = new AfterObserver(v => this.BytesRead += Math.Max(0, v));
            this.AfterWrite = new AfterObserver(v => this.BytesWritten += Math.Max(0, v));
        }

        /// <summary>
        /// Gets the bytes read.
        /// </summary>
        /// <value>
        /// The bytes read.
        /// </value>
        public long BytesRead { get; private set; }

        /// <summary>
        /// Gets the bytes written.
        /// </summary>
        /// <value>
        /// The bytes written.
        /// </value>
        public long BytesWritten { get; private set; }

        private class AfterObserver : IObserver<int>
        {
            private readonly Action<int> onNext;

            public AfterObserver(Action<int> onNext)
            {
                this.onNext = onNext;
            }

            public void OnNext(int value)
            {
                onNext(value);
            }

            public void OnError(Exception error)
            {
            }

            public void OnCompleted()
            {
            }
        }
    }
}
